package com.lxm.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.lxm.common.contants.LoginConstants;
import com.lxm.common.contants.RedisExpire;
import com.lxm.common.contants.UserConstants;
import com.lxm.common.tools.UserHolder;
import com.lxm.dto.*;
import com.lxm.entity.Login;
import com.lxm.mapper.LoginDao;
import com.lxm.service.LoginService;
import com.lxm.service.UtilsService;
import com.lxm.vo.LoginVO;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.util.concurrent.TimeUnit;

/**
 * <p>
 * 用户登录表 服务实现类
 * </p>
 *
 * @author ${author}
 * @since 2024-10-02
 */
@Service
public class LoginServiceImpl extends ServiceImpl<LoginDao, Login> implements LoginService {
    @Resource
    private UtilsService utilsService;
    @Resource
    private StringRedisTemplate stringRedisTemplate;

    @Override
    public Result loginByPhone(PhonePwdLoginDTO login, HttpServletResponse response) {
        //判断手机号和密码参数是否为空
        if (StrUtil.isBlank(login.getPhone()) || StrUtil.isBlank(login.getPwd())) {
            return Result.fail(LoginConstants.PHONE_PASSWORD_LOGIN_IS_NULL);
        }
        //查询数据库校验，这里只让SQL返回LoginVO所需要的字段，优化下性能
        Login userLogin = lambdaQuery()
                .eq(Login::getPhone, login.getPhone())
                .eq(Login::getPwd, login.getPwd())
                .select(Login::getUserId, Login::getNickName, Login::getIcon)
                .one();
        //判断是否正确
        if (BeanUtil.isEmpty(userLogin)) {
            return Result.fail(LoginConstants.PHONE_PASSWORD_LOGIN_ERROR);
        }
        LoginVO loginVO = BeanUtil.toBean(userLogin, LoginVO.class);
        loginVO.setIsAdmin(0);
        //生成Token并返回
        utilsService.TWTToken(response, loginVO);
        return Result.ok(LoginConstants.USER_LOGIN_SUCCESS);
    }


    @Override
    public Result loginByNickName(NickNamePwdLoginDTO login, HttpServletResponse response) {
        //判断昵称和密码参数是否为空
        if (StrUtil.isBlank(login.getNickName()) || StrUtil.isBlank(login.getPwd())) {
            return Result.fail(LoginConstants.NICK_NAME_PASSWORD_LOGIN_IS_NULL);
        }
        //查询数据库校验，这里只让SQL返回LoginVO所需要的字段，优化下性能
        Login userLogin = lambdaQuery()
                .eq(Login::getNickName, login.getNickName())
                .eq(Login::getPwd, login.getPwd())
                .select(Login::getUserId, Login::getNickName, Login::getIcon)
                .one();
        //判断是否正确
        if (BeanUtil.isEmpty(userLogin)) {
            return Result.fail(LoginConstants.NICK_NAME_PASSWORD_LOGIN_ERROR);
        }
        LoginVO loginVO = BeanUtil.toBean(userLogin, LoginVO.class);
        loginVO.setIsAdmin(0);
        //生成Token并返回
        utilsService.TWTToken(response, loginVO);
        return Result.ok(LoginConstants.USER_LOGIN_SUCCESS);
    }

    @Override
    public Result loginByPhoneCode(PhoneCodeLoginDTO phoneCodeLoginDTO, HttpServletResponse response) {
        //判断手机号和验证码参数是否为空
        if (StrUtil.isBlank(phoneCodeLoginDTO.getPhone()) ||
                StrUtil.isBlank(phoneCodeLoginDTO.getCode())) {
            return Result.fail(LoginConstants.PHONE_CODE_LOGIN_IS_NULL);
        }
        //判断验证码是否正确
        String code = stringRedisTemplate.opsForValue()
                .get(UserConstants.USER_PHONE + phoneCodeLoginDTO.getPhone());
        if (!phoneCodeLoginDTO.getCode().equals(code)) {
            return Result.fail(LoginConstants.PHONE_CODE_LOGIN_CODE_ERROR);
        }
        //这里只让SQL返回LoginVO所需要的字段，优化下性能
        Login userLogin = lambdaQuery()
                .eq(Login::getPhone, phoneCodeLoginDTO.getPhone())
                .select(Login::getUserId, Login::getNickName, Login::getIcon)
                .one();
        //将Login转化为LoginVO
        LoginVO loginVO = BeanUtil.toBean(userLogin, LoginVO.class);
        loginVO.setIsAdmin(0);
        utilsService.TWTToken(response, loginVO);
        return Result.ok(LoginConstants.USER_LOGIN_SUCCESS);
    }

    //退出登录
    @Override
    public String logout(HttpServletRequest request) {
        String token = request.getHeader(LoginConstants.TOKEN_HEADER);
        stringRedisTemplate.opsForValue()
                .set(UserConstants.USER_TOKEN + token, "1");
        stringRedisTemplate
                .expire(UserConstants.USER_TOKEN + token,
                        RedisExpire.TOKEN_EXPIRE, TimeUnit.SECONDS);
        return LoginConstants.LOGOUT_SUCCESS;
    }

    @Override
    public Login getUserInfoLogin(Long userId) {
        return lambdaQuery()
                .eq(Login::getUserId, userId)
                .select(Login::getIcon, Login::getNickName)
                .one();
    }

    @Override
    public Result updateNickNameAndIcon(UserNickNameAndIconModifyDTO user) {
        Long userId = UserHolder.getUser().getUserId();
        Login login = BeanUtil.toBean(user, Login.class);
        boolean update = update(login, new LambdaQueryWrapper<Login>()
                .eq(Login::getUserId, userId));
        if (!update) return Result.fail(UserConstants.MODIFY_NICK_NAME_AND_ICON_FAIL);
        return Result.ok();
    }
}
